package com.net.jef.dal.common;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;

import javax.persistence.Id;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public abstract class BaseDAOHibernate<M extends java.io.Serializable, PK extends java.io.Serializable> {

    protected static final Logger LOGGER = LoggerFactory
            .getLogger(BaseDAOHibernate.class);

    private final Class<M> entityClass;
    private final String HQL_LIST_ALL;
    private final String HQL_COUNT_ALL;
    private final String HQL_OPTIMIZE_PRE_LIST_ALL;
    private final String HQL_OPTIMIZE_NEXT_LIST_ALL;
    private String pkName = null;

    @SuppressWarnings("unchecked")
    public BaseDAOHibernate() {
        this.entityClass = (Class<M>) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
        Field[] fields = this.entityClass.getDeclaredFields();
        for (Field f : fields) {
            if (f.isAnnotationPresent(Id.class)) {
                this.pkName = f.getName();
            }
        }

        // TODO @Entity name not null
        HQL_LIST_ALL = "from " + this.entityClass.getSimpleName()
                + " order by " + pkName + " desc";
        HQL_OPTIMIZE_PRE_LIST_ALL = "from " + this.entityClass.getSimpleName()
                + " where " + pkName + " > ? order by " + pkName + " asc";
        HQL_OPTIMIZE_NEXT_LIST_ALL = "from " + this.entityClass.getSimpleName()
                + " where " + pkName + " < ? order by " + pkName + " desc";
        HQL_COUNT_ALL = " select count(*) from "
                + this.entityClass.getSimpleName();
    }

    @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;

    public Session getSession() {
        // 事务必须是开启的(Required)，否则获取不到
        return sessionFactory.getCurrentSession();
    }

    @SuppressWarnings("unchecked")
    public PK save(M model) {
        return (PK) getSession().save(model);
    }

    public void saveOrUpdate(M model) {
        getSession().saveOrUpdate(model);
    }

    public void update(M model) {
        getSession().update(model);

    }

    public void merge(M model) {
        getSession().merge(model);
    }

    public void delete(PK id) {
        getSession().delete(this.get(id));

    }

    public void deleteObject(M model) {
        getSession().delete(model);

    }

    public boolean exists(PK id) {
        return get(id) != null;
    }

    public M get(PK id) {
        return (M) getSession().get(this.entityClass, id);
    }

}